﻿using Basic.FlowApplication.Extend;
using Basic.FlowApplication.Interface;
using Basic.FlowApplication.Linq;
using Basic.FlowApplication.Model;
using Basic.FlowApplication.Model.AuditLog;
using Basic.FlowRemoteModel;
using Basic.FlowRemoteModel.Application.Model;
using WeDonekRpc.Client.Attr;
using WeDonekRpc.Helper;

namespace Basic.FlowApplication.AuditEvent
{
    /// <summary>
    /// 审核未通过
    /// </summary>
    [WeDonekRpc.Client.Attr.IocName("Audit_1")]
    [ClassLifetimeAttr(ClassLifetimeType.SingleInstance)]
    internal class AuditNoPassEvent : IItemAuditEvent
    {
        public AfootAuditLogItem ItemAudit ( AuditFlowBody flow, FlowAuditLogState log, AuditRes result )
        {
            AfootAuditLogItem item = log.LogItem.Find(a => a.Id == result.ItemId);
            item.CheckAuditItem(result);
            item.AuditState = FlowAuditItemStatus.审核未通过;
            item.AuditOpinion = result.Opinion;
            item.SignFileId = result.SignFileId;
            FlowNode node = flow.Nodes[item.NodeId];
            if ( !this._IsNoPass(node, item, log) )
            {
                item.NodeStatus = FlowNodeAuditStatus.审核进行中;
            }
            else
            {
                this._ToVoideNode(flow, log, node, item);
            }
            return item;
        }
        private void _ToVoideNode ( AuditFlowBody flow, FlowAuditLogState log, FlowNode node, AfootAuditLogItem item )
        {
            Tuple<FlowNode, long> t = flow.GetBranchNode(node);
            if ( t == null )
            {
                return;
            }
            if ( log.CheckIsNoPass(t.Item1, t.Item2) )
            {
                long[] nodeId = log.LogItem.Where(c => c.RootNodeId == node.RootNodeId && ( c.Status == FlowAuditItemStatus.审核进行中 || c.Status == FlowAuditItemStatus.待开始 )).Select(c => c.NodeId).Distinct().ToArray();
                if ( !nodeId.IsNull() )
                {
                    nodeId = flow.CheckIsToVoid(t.Item1, nodeId);
                    if ( nodeId.Length > 0 )
                    {
                        log.LogItem.ForEach(c =>
                        {
                            if ( nodeId.Contains(c.NodeId) && ( c.Status == FlowAuditItemStatus.审核进行中 || c.Status == FlowAuditItemStatus.待开始 ) )
                            {
                                c.Status = FlowAuditItemStatus.已作废;
                                c.OptItemId = item.Id;
                            }
                        });
                    }
                }
            }
        }
        private bool _IsNoPass ( FlowNode node, AfootAuditLogItem item, FlowAuditLogState log )
        {
            if ( node.AuditType == FlowAuditType.独立审批 )
            {
                return true;
            }
            else if ( this._MultipleIsToVoid(node, item, log) )
            {
                log.LogItem.ForEach(c =>
                {
                    if ( c.NodeId == node.Id && c.Status == FlowAuditItemStatus.审核进行中 )
                    {
                        c.Status = FlowAuditItemStatus.已作废;
                        c.OptItemId = item.Id;
                    }
                });
                return true;
            }
            return false;
        }
        private bool _MultipleIsToVoid ( FlowNode node, AfootAuditLogItem item, FlowAuditLogState log )
        {
            if ( node.AuditNoPassOpt == FlowOutNoPassOptMethod.一票否决 || node.MinAuditPass.HasValue == false )
            {
                return true;
            }
            List<AfootAuditLogItem> states = log.LogItem.FindAll(a => a.NodeId == item.NodeId && a.RootBatchNo == item.RootBatchNo);
            states = states.Filters(item);
            if ( states.Count == 1 || ( node.IsRatio == false && node.MinAuditPass.Value >= states.Count ) )
            {
                return true;
            }
            int num = states.Count(c => c.Status == FlowAuditItemStatus.审核未通过);
            if ( node.IsRatio )
            {
                num = num * 100 / states.Count;
                return num > ( 100 - node.MinAuditPass.Value );
            }
            return num > ( states.Count - node.MinAuditPass.Value );
        }
    }
}
